// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include <stdio.h>
#include "objbase.h"
#include "MSCorEE.h"
#import "C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.tlb" raw_interfaces_only
using namespace mscorlib; 

void Bootstrap() {
	OutputDebugString(L"MceFM Bootstrap Started");

	FILE* file = NULL; // fopen("C:\\mcefm_bs.log", "w");
	if(file) {
		fprintf(file, "Bootstrap started\n");
		OutputDebugString(L"Log file created");
	} else {
		OutputDebugString(L"Log file NOT created");
	}

	CoInitializeEx(0, COINIT_MULTITHREADED );
	ICorRuntimeHost* pICorRuntimeHost = 0;
	HRESULT st = CoCreateInstance(CLSID_CorRuntimeHost, 0, CLSCTX_ALL, IID_ICorRuntimeHost, (void**)&pICorRuntimeHost);
	if(!pICorRuntimeHost) {
		if(file) {
			fprintf(file, "CoCreateInstance failed with %d\n", st);
			fclose(file);
		}
		return;
	}
	HDOMAINENUM hEnum = NULL;
	pICorRuntimeHost->EnumDomains(&hEnum); 

	if(!hEnum) {
		if(file) {
			fprintf(file, "EnumDomains failed\n");
			fclose(file);
		}
		return;
	}

	IUnknown* pUunk = 0;
	st = pICorRuntimeHost->NextDomain(hEnum, &pUunk);
	if(!pUunk) {
		if(file) {
			fprintf(file, "NextDomain failed\n");
			fclose(file);
		}
		return;
	}
	_AppDomain * pCurDomain = NULL;
    st = pUunk->QueryInterface(__uuidof(_AppDomain), (VOID**)&pCurDomain);
	if(!pCurDomain) {
		if(file) {
			fprintf(file, "QueryInterface failed\n");
			fclose(file);
		}
		return;
	}

	_bstr_t assemblyName = "Last, Version=1.2.0.0, Culture=neutral, PublicKeyToken=b83b7899bf5408c9";
	_bstr_t typeName = "MceFM.Last.Inject.Injectee";
	
	_ObjectHandle* pObjectHandle = 0;

	pCurDomain->CreateInstance(assemblyName, typeName, &pObjectHandle);
	
	if(file) {
		fprintf(file, "Bootstrap finished\n");
		fclose(file);
	}
}


BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		Bootstrap();
		break;
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

